﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;

namespace fsplit_spec
{
    [TestClass]
    public class basics
    {
        [TestMethod]
        public void exeplan1()
        {
            //Arrange
            ulong total_size = 15;
            uint split_size = 4;

            //Act
            fsplit.DissolutionPlan plan = fsplit.Fmerge.GetDissolutionPlan(total_size, split_size);

            //Assert
            Assert.IsNotNull(plan);
            Assert.AreEqual<uint>(4, plan.PartCount);
            Assert.AreEqual<uint>(3, plan.RemainBytes);
            Assert.AreEqual<uint>(4, plan.PartSize);
            Assert.AreEqual<uint>((uint)total_size, plan.RemainBytes == 0U ? plan.PartSize * plan.PartCount : plan.PartSize * (plan.PartCount - 1) + plan.RemainBytes);
            Assert.AreEqual<ulong>(total_size, plan.SourceSize);
        }
        [TestMethod]
        public void exeplan2()
        {
            //Arrange
            ulong total_size = 4;
            uint split_size = 15;

            //Act
            fsplit.DissolutionPlan plan = fsplit.Fmerge.GetDissolutionPlan(total_size, split_size);

            //Assert
            Assert.IsNotNull(plan);
            Assert.AreEqual<uint>(1, plan.PartCount);
            Assert.AreEqual<uint>(4, plan.RemainBytes);
            Assert.AreEqual<uint>(4, plan.PartSize);
            Assert.AreEqual<uint>((uint)total_size, plan.RemainBytes == 0U ? plan.PartSize * plan.PartCount : plan.PartSize * (plan.PartCount - 1) + plan.RemainBytes);
            Assert.AreEqual<ulong>(total_size, plan.SourceSize);
        }
        [TestMethod]
        public void exeplan3()
        {
            //Arrange
            ulong total_size = 16;
            uint split_size = 4;

            //Act
            fsplit.DissolutionPlan plan = fsplit.Fmerge.GetDissolutionPlan(total_size, split_size);

            //Assert
            Assert.IsNotNull(plan);
            Assert.AreEqual<uint>(4, plan.PartCount);
            Assert.AreEqual<uint>(0, plan.RemainBytes);
            Assert.AreEqual<uint>(4, plan.PartSize);
            Assert.AreEqual<uint>((uint)total_size, plan.RemainBytes == 0U ? plan.PartSize * plan.PartCount : plan.PartSize * (plan.PartCount - 1) + plan.RemainBytes);
            Assert.AreEqual<ulong>(total_size, plan.SourceSize);
        }
        [TestMethod]
        public void basic1()
        {
            //Arrange
            var data = new byte[fsplit.Fmerge._1Kb * 12U];
            ulong total_size = (ulong)data.LongLength;
            uint split_size = fsplit.Fmerge._1Kb;
            var stream = new System.IO.MemoryStream(data);
            var target = new MemoryTarget();

            //Act
            var result = fsplit.Fmerge.Split(stream, split_size, target, "");

            //Assert
            Assert.AreEqual<ulong>(total_size, (ulong)stream.Length);
            Assert.IsNotNull(result.Target);
            Assert.AreEqual<uint>(12U, (uint)result.Target.Parts.Count);
            Assert.AreEqual<ulong>(total_size, (ulong)result.Target.Parts.Sum(p => p.part_size));
        }
        [TestMethod]
        public void basic2()
        {
            //Arrange
            var data = new byte[2700];
            ulong total_size = (ulong)data.LongLength;
            uint split_size = 500;
            var stream = new System.IO.MemoryStream(data);
            var target = new MemoryTarget();

            //Act
            var result = fsplit.Fmerge.Split(stream, split_size, target, "");

            //Assert
            Assert.AreEqual<ulong>(total_size, (ulong)stream.Length);
            Assert.IsNotNull(result.Target);
            Assert.AreEqual<string>("Created 6 parts:", result.ResultLabel);
            Assert.AreEqual<uint>(6U, (uint)result.Target.Parts.Count);
            Assert.AreEqual<ulong>(total_size, (ulong)result.Target.Parts.Sum(p => p.part_size));
        }

        class MemoryTarget : fsplit.ITarget
        {
            private List<fsplit.Part> parts;
            public MemoryTarget()
            {
                parts = new List<fsplit.Part>();
            }
            public IList<fsplit.Part> Parts
            {
                get { return parts; }
            }
            public System.IO.Stream CreateDestination(uint total, int part_size)
            {
                ushort part_id = (ushort)(parts.Count + 1);
                parts.Add(new fsplit.Part() { part_id = part_id, part_size = (uint)part_size });
                return new System.IO.MemoryStream();
            }
        }
    }
}